home *** CD-ROM | disk | FTP | other *** search
- Path: chronicle.mti.sgi.com!austern
- From: Philippe Verdy <100105.3120@compuserve.com>
- Newsgroups: comp.std.c++
- Subject: constness of private members and methods
- Date: 25 Mar 1996 10:04:56 PST
- Organization: CompuServe Incorporated
- Approved: austern@isolde.mti.sgi.com
- Message-ID: <4j49e0$8fo@dub-news-svc-4.compuserve.com>
- NNTP-Posting-Host: isolde.mti.sgi.com
- X-Original-Date: 24 Mar 1996 19:56:48 GMT
- X-Auth: PGPMoose V1.1 PGP comp.std.c++
- iQBVAwUBMVbgV0y4NqrwXLNJAQFmJQH/WLQML6cwTrsQ7ff4Ill7GUEKrP/5hjog
- QP9gzv3KSMjbkVEL1oCxfrb+uj9E8o9kobAJQkYRF7KKOHppoVe7rA==
- =Mt3Q
- Originator: austern@isolde.mti.sgi.com
-
- Many recursive data structures require algorithms to handle
- them which have to mark and unmark all scanned objects in
- order to avoid infinite recursion when walking on that
- structure, or when building items iterator.
- Such algorithms will use the mark() and unmark() private
- methods in each visited node, so that we can detect paths
- which have already been visited. his is critical for example
- when managing with auto-references, graphs, dictionnaries
- of polymorphic objects (containing dictionnaries like in
- a PostScript interpret).
- However, how can we apply standard read-only methods on such
- objects: these methods are specified as const in one of the
- base classes, and virtual override requires not to change the
- constness of the derived object.
- So we cannot mark such structures, because even a private
- member cannot be modified in a const instance.
- We can effectively change temporarily the constness of the
- object to realize this mark, but in that case we would write
- the following :
- class T {
- public:
- T() { ...; _mark = 0; }
- virtual ~T();
-
- virtual void show() const;
- protected:
- void mark() { _mark = 1; }
- void unmark() { _mark = 0; }
- bool ismarked() const { return _mark; }
- private:
- char _mark;
- }
- The problem is that now mark() and unmark() methods are not
- const so they cannot be used in read-only methods like show().
- So we have to use a const_cast<T&> or const_cast<T*> to
- suppress this constness.
-
- This is not obvious, and has the big disadvantage of globally
- suppressing the constness of the object. So this is quite
- dangerous, because some-times, we do not know really if a
- method has an impact on the semantic value of the instance
- on which we apply this cast. So this is a security hole which
- should be avoided.
-
- We can avoid const_casting to call mark() and unmark() by
- declaring them as const, like this:
- protected:
- void mark() const { (const_cast<T*>this)->_mark = 1; }
- void unmark() const { (const_cast<T*>this)->_mark = 0; }
- but this is really hard to write, and is it semantically
- correct ? It would from the public point of view, but what
- on the private point of view ?
-
- We can also use explicitly (const_cast<T*>this)->mark(); and
- (const_cast<T*>this)->unmark(); calls in the show()
- implementation, but this is quite hard to write, so that many
- users refrain using const specifiers on their classes.
-
- Is there any way (or proposal) to explicitly specify members
- of a class definition which are relaxed on constness certi-
- fication ?
-
- Would not it be great if we could simply define such members
- as "unconst" like in the following example :
-
- class T {
- public:
- T() { ...; _mark = 0; }
- virtual ~T();
-
- virtual void show() const;
- protected:
- void mark() const { _mark = 1; } // RELAXED HERE
- void unmark() const { _mark = 0; } // RELAXED HERE
- bool ismarked() const { return _mark; }
- private:
- unconst char _mark; // HERE IS WHERE THIS APPLIES
- }
-
- In that example, even thow the mark() and unmark() methods
- are const-specified, we are allowed to modify the _mark
- member, because it has been explicitly relaxed.
-
- We could restrict the unconst modifier usage to private
- or protected members declaration only, so that the public
- interface of a class would keep the constness integrity.
-
- This way, the dangerous const_cast<> operator could be avoided
- most of the time and isolated in specific class
- implementations (for compatibility with not const-compliant
- C libraries)...
-
- What do you think ?
-
- And is constness definition a semantic only definition,
- or does it involve a more strict sense in which the compiler
- optimizer would have an influence (such as in common
- subexpressions reduction) ?
- ---
- [ comp.std.c++ is moderated. To submit articles: Try just posting with your
- newsreader. If that fails, use mailto:std-c++@ncar.ucar.edu
- comp.std.c++ FAQ: http://reality.sgi.com/austern/std-c++/faq.html
- Moderation policy: http://reality.sgi.com/austern/std-c++/policy.html
- Comments? mailto:std-c++-request@ncar.ucar.edu
- ]
-